<?php

namespace app\admin\model\tongcheng;

use addons\tongcheng\enum\DeliveryOrderStatus;
use addons\tongcheng\enum\DeliveryTransferStatus;
use addons\tongcheng\enum\UserRole;
use addons\tongcheng\enum\WebSocketBackendAction;
use addons\tongcheng\enum\WebSocketClientAction;
use addons\tongcheng\library\WebSocketService;
use addons\tongcheng\model\BaseModel;
use addons\tongcheng\model\DeliveryOrderModel;
use addons\tongcheng\model\RiderModel;
use think\Db;


class DeliveryTransferModel extends BaseModel
{
    // 表名
    protected $name = 'tongcheng_delivery_transfer';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'integer';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = false;

    // 追加属性
    protected $append = [
        'role_text',
        'status_text',
        'expire_time_text',
        'complete_time_text'
    ];


    public function getRoleList()
    {
        return ['ADMIN' => __('Role admin'), 'RIDER' => __('Role rider')];
    }

    public function getStatusList()
    {
        return ['0' => __('Status 0'), '1' => __('Status 1'), '2' => __('Status 2')];
    }


    public function getRoleTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['role']) ? $data['role'] : '');
        $list  = $this->getRoleList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
        $list  = $this->getStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getExpireTimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['expire_time']) ? $data['expire_time'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getCompleteTimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['complete_time']) ? $data['complete_time'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    protected function setExpireTimeAttr($value)
    {
        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
    }

    protected function setCompleteTimeAttr($value)
    {
        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
    }


    public function zone()
    {
        return $this->belongsTo(ZoneModel::class, 'zone_id', 'id', [], 'LEFT')->setEagerlyType(0);
    }

    public function order()
    {
        return $this->belongsTo(DeliveryOrderModel::class, 'order_id', 'id', [], 'LEFT')->setEagerlyType(0);
    }

    public function rider()
    {
        return $this->belongsTo(RiderModel::class, 'user_id', 'user_id', [], 'LEFT')->setEagerlyType(0);
    }

    public function target()
    {
        return $this->belongsTo(RiderModel::class, 'user_id', 'user_id', [], 'LEFT')->setEagerlyType(0);
    }

    /**
     * 验证转单数据
     * @param $order_id
     * @param $target_id
     * @return array
     */
    public static function valid($order_id, $user_id, $target_id)
    {
        // if ($user_id == $target_id) {
        //     tongcheng_fail('不能转单给自己');
        // }
        if (self::where('order_id', $order_id)->where('status', DeliveryTransferStatus::CREATE)->count()) {
            tongcheng_fail('该订单已存在未处理的转单请求，请勿重复操作');
        }
        if (!$target_rider = RiderModel::where('id', $target_id)->find()) {
            tongcheng_fail('目标骑手不存在');
        }
        if ($target_rider->status != 1) {
            tongcheng_fail('目标骑手状态异常');
        }
        if ($target_rider->work_status != 1) {
            tongcheng_fail('目标骑手非工作状态');
        }

        if (!$order = DeliveryOrderModel::where('id', $order_id)->find()) {
            tongcheng_fail('配送订单不存在');
        }
        if ($order->status != DeliveryOrderStatus::RECEIVED) {
            tongcheng_fail('配送订单非接单状态，无法转单');
        }
        if ($order['rider_id'] != $user_id) {
            tongcheng_fail('该订单不属于您，无法转单');
        }

        return [
            'order'        => $order,
            'target_rider' => $target_rider,
        ];
    }

    /**
     * 发起转单
     * @param $zone_id
     * @param $user_id
     * @param $order_id
     * @param $target_id
     * @param $role
     * @return DeliveryTransferModel
     */
    public static function add($zone_id, $user_id, $order_id, $target_id, $role = UserRole::RIDER, $operate_user_id = 0)
    {
        $data         = self::valid($order_id, $user_id, $target_id);
        $rider        = RiderModel::where('user_id', $user_id)->find();
        $order        = $data['order'];
        $target_rider = $data['target_rider'];

        // 转单自动取消时间（分钟）
        $auto_cancel_transfer = SystemConfigModel::getValue('auto_cancel_transfer');
        $auto_cancel_transfer = $auto_cancel_transfer ?: 3;// 默认3分钟

        Db::startTrans();
        try {
            // 创建转单记录
            $transfer = DeliveryTransferModel::create([
                'zone_id'     => $zone_id,
                'role'        => $role,
                'order_id'    => $order_id,
                'user_id'     => $user_id,
                'target_id'   => $target_id,
                'status'      => DeliveryTransferStatus::CREATE,
                'expire_time' => time() + $auto_cancel_transfer * 60,
            ]);

            // 订单操作记录
            DeliveryOrderActionModel::create([
                'order_id'        => $order_id,
                'operate_role'    => $role,
                'operate_user_id' => $operate_user_id ?: $user_id,
                'order_status'    => $data['order']['status'],
                'refund_status'   => $data['order']['refund_status'],
                'remark'          => "骑手【{$rider['real_name']}】发起转单，目标骑手：{$target_rider['real_name']}",
            ]);
            Db::commit();

            tongcheng_defer_exec(function () use ($order, $transfer, $target_id) {
                // 长连接通知 - 通知骑手 - 骑手转单请求
                WebSocketService::send(WebSocketBackendAction::SEND_TO_USER, [
                    'order_id'    => $order['id'],
                    'transfer_id' => $transfer['id'],
                ], WebSocketClientAction::DELIVERY_TRANSFER_CREATE, $target_id, $order['zone_id']);
            });

            return $transfer;
        } catch (\Exception $e) {
            Db::rollback();
            tongcheng_fail($e->getMessage());
        }
    }

    /**
     * 同意转单
     * @param $id
     * @param $user_id
     * @return DeliveryTransferModel|void|null
     */
    public static function agree($id, $user_id)
    {
        $transfer = self::get([
            'id'        => $id,
            'target_id' => $user_id,
        ]);
        if (!$transfer) {
            tongcheng_fail('转单记录不存在');
        }
        if ($transfer->status != DeliveryTransferStatus::CREATE) {
            tongcheng_fail('转单记录状态异常');
        }

        $order = DeliveryOrderModel::get($transfer->order_id);
        if (!$order) {
            tongcheng_fail('配送订单不存在');
        }
        if ($order->status != DeliveryOrderStatus::RECEIVED) {
            tongcheng_fail('配送订单非接单状态，无法同意该转单');
        }

        $target_rider = RiderModel::where('user_id', $user_id)->find();
        Db::startTrans();
        try {
            // 更新转单状态
            $transfer->status        = DeliveryTransferStatus::AGREE;
            $transfer->complete_time = time();
            $transfer->save();

            // 更新订单状态
            $order->status   = DeliveryOrderStatus::RECEIVED;
            $order->rider_id = $user_id;
            $order->save();

            // 订单操作记录
            DeliveryOrderActionModel::create([
                'order_id'        => $order['id'],
                'operate_role'    => UserRole::RIDER,
                'operate_user_id' => $user_id,
                'order_status'    => $order['status'],
                'refund_status'   => $order['refund_status'],
                'remark'          => "骑手【{$target_rider['real_name']}】同意转单，订单状态更新为：已接单",
            ]);
            Db::commit();

            tongcheng_defer_exec(function () use ($order, $transfer) {
                // 长连接通知 - 通知骑手 - 骑手同意转单
                WebSocketService::send(WebSocketBackendAction::SEND_TO_USER, [
                    'order_id'    => $order['id'],
                    'transfer_id' => $transfer['id'],
                ], WebSocketClientAction::DELIVERY_TRANSFER_AGREE, $transfer['user_id'], $order['zone_id']);
            });

            return $transfer;
        } catch (\Exception $e) {
            Db::rollback();
            tongcheng_fail($e->getMessage());
        }
    }

    /**
     * 拒绝转单
     * @param $id
     * @param $user_id
     * @return DeliveryTransferModel|void|null
     */
    public static function refuse($id, $user_id)
    {
        $transfer = self::get([
            'id'        => $id,
            'target_id' => $user_id,
        ]);
        if (!$transfer) {
            tongcheng_fail('转单记录不存在');
        }
        if ($transfer->status != DeliveryTransferStatus::CREATE) {
            tongcheng_fail('转单记录状态异常');
        }

        $order = DeliveryOrderModel::get($transfer->order_id);
        if (!$order) {
            tongcheng_fail('配送订单不存在');
        }
        if ($order->status != DeliveryOrderStatus::RECEIVED) {
            tongcheng_fail('配送订单非接单状态，无法拒绝该转单');
        }

        $target_rider = RiderModel::where('user_id', $user_id)->find();
        Db::startTrans();
        try {
            // 更新转单状态
            $transfer->status        = DeliveryTransferStatus::REFUSE;
            $transfer->complete_time = time();
            $transfer->save();

            // 订单操作记录
            DeliveryOrderActionModel::create([
                'order_id'        => $order['id'],
                'operate_role'    => UserRole::RIDER,
                'operate_user_id' => $user_id,
                'order_status'    => $order['status'],
                'refund_status'   => $order['refund_status'],
                'remark'          => "骑手【{$target_rider['real_name']}】拒绝转单",
            ]);
            Db::commit();

            tongcheng_defer_exec(function () use ($order, $transfer) {
                // 长连接通知 - 通知骑手 - 骑手拒绝转单
                WebSocketService::send(WebSocketBackendAction::SEND_TO_USER, [
                    'order_id'    => $order['id'],
                    'transfer_id' => $transfer['id'],
                ], WebSocketClientAction::DELIVERY_TRANSFER_REFUSE, $transfer['user_id'], $order['zone_id']);
            });

            return $transfer;
        } catch (\Exception $e) {
            Db::rollback();
            tongcheng_fail($e->getMessage());
        }
    }

    /**
     * 转单过期自动取消
     * @param $transfer
     * @return void
     */
    public static function expire($transfer)
    {
        if (!$transfer) {
            return;
        }
        if ($transfer->status != DeliveryTransferStatus::CREATE) {
            return;
        }

        $order = DeliveryOrderModel::get($transfer->order_id);
        if (!$order) {
            return;
        }
        if ($order->status != DeliveryOrderStatus::RECEIVED) {
            return;
        }

        // $target_rider = RiderModel::where('user_id', $transfer->target_id)->find();
        Db::startTrans();
        try {
            // 更新转单状态
            $transfer->status        = DeliveryTransferStatus::EXPIRE;
            $transfer->complete_time = time();
            $transfer->save();

            // 订单操作记录
            DeliveryOrderActionModel::create([
                'order_id'        => $order['id'],
                'operate_role'    => UserRole::SYSTEM,
                'operate_user_id' => 0,
                'order_status'    => $order['status'],
                'refund_status'   => $order['refund_status'],
                'remark'          => "转单请求已过期，系统自动取消",
            ]);
            Db::commit();

            tongcheng_defer_exec(function () use ($order, $transfer) {
                // 长连接通知 - 通知骑手 - 转单请求已过期
                WebSocketService::send(WebSocketBackendAction::SEND_TO_USER, [
                    'order_id'    => $order['id'],
                    'transfer_id' => $transfer['id'],
                ], WebSocketClientAction::DELIVERY_TRANSFER_EXPIRE, $transfer['user_id'], $order['zone_id']);
            });
        } catch (\Exception $e) {
            Db::rollback();
        }
    }
}
